package com.nowcoder.community.config;

import com.nowcoder.community.service.UserService;
import com.nowcoder.community.utils.CommunityConstant;
import com.nowcoder.community.utils.CommunityUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter implements CommunityConstant {

    @Autowired
    private UserService userService;


    @Override
    public void configure(WebSecurity web) throws Exception {
        //忽略对静态资源的访问
        web.ignoring().antMatchers("/resources/**");
    }

    //授权配置

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //授权
        //以下路径只要有任一权限，即可访问
        http.authorizeRequests().antMatchers(
                "/user/setting",
                "/user/upload",
                "/letter/**",
                "/notice/**",
                "follow",
                "unfollow",
                "/comment/add/**",
                "/discuss/add"
        ).hasAnyAuthority(
                AUTHORITY_USER,
                AUTHORITY_ADMIN,
                AUTHORITY_MODERATOR
                //除了这些请求外，其余的都允许
        ).antMatchers(
                "/discuss/top",
                "/discuss/wonderful"
        ).hasAnyAuthority(
                AUTHORITY_MODERATOR
        ).antMatchers(
                "/discuss/delete",
                "/data/**"
        ).hasAnyAuthority(
                AUTHORITY_ADMIN
        ).anyRequest().permitAll()
        .and().csrf().disable();

        //权限不够时的处理
        //有可能是没有登录/权限不足
        //还需要区分请求是不是异步，做处理
        http.exceptionHandling()
                .authenticationEntryPoint(new AuthenticationEntryPoint() {
                    //没有登录
                    @Override
                    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
                        //区分异步请求还是同步请求的方法：判断请求头是否有x-requested-with:XMLHttpRequest,
                        String xRequestWith = request.getHeader("x-requested-with");
                        if ("XMLHttpRequest".equals(xRequestWith)) {
                            //是异步请求，直接返回json
                            response.setContentType("application/plain;charset=utf-8");
                            PrintWriter writer = response.getWriter();
                            writer.write(CommunityUtil.getJSONString(403, "你还没有登录!"));
                        } else {
                            response.sendRedirect(request.getContextPath() + "/login");
                        }
                    }
                })
                .accessDeniedHandler(new AccessDeniedHandler() {
                    //权限不足
                    @Override
                    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
                        //区分异步还是同步
                        String xRequestWith = request.getHeader("x-requested-with");
                        if ("XMLHttpRequest".equals(xRequestWith)) {
                            //是异步请求
                            response.setContentType("application/plain;charset=utf-8");
                            PrintWriter writer = response.getWriter();
                            writer.write(CommunityUtil.getJSONString(403, "你没有访问此功能的权限!"));
                        } else {
                            response.sendRedirect(request.getContextPath() + "/denied");
                        }
                    }
                });
        //Security底层会默认拦截/logout请求，进行退出处理
        //覆盖它默认的逻辑，才能执行我们自己的退出代码
        http.logout().logoutUrl("/securitylogout");
    }


    //认证配置


    //CSRF配置


}
